var logger = require('log4js').getLogger();
var httpRequire = require('request');
var xml2js = require('xml2js');
var md5 = require('md5');
var Random = require("../utils/random");
var TimeUtils = require("../utils/timeUtils");
var rechargeConfig = require('../../../app/conf/config.json');

var RechargeService = {};

// 玩一玩
RechargeService.handleWyxPay = function (params, callback) {
    logger.info("handleWyxPay, params: %j", params);

    if(!params){
        logger.error("invalid handleWyxPay params");
        callback({resultCode : 404, msg : "invalid params"});
        return;
    }

    if(params.gameid !== 2352 && params.gameid !== "2352"){
        logger.error("invalid handleWyxPay gameid");
        callback({resultCode : 404, msg : ""});
        return;
    }

    if(!params.itemid || params.itemid < 9 || params.itemid > 16){
        logger.error("invalid handleWyxPay itemid");
        callback({resultCode : 404, msg : ""});
        return;
    }

    // 给gameserver发送HTTP充值请求
    var rechargeParams = {};
    rechargeParams.channel = params.gameid;
    rechargeParams.uid = params.uid;
    rechargeParams.itemIndex = params.itemid - 9; //9 START
    rechargeParams.orderId = params.orderid;
    rechargeParams.totalFee = 100;
    rechargeParams.rechargeType = 'wyw';
    RechargeService.sendHttpToGameServer(rechargeParams, callback);
};

// 微信支付预支付
RechargeService.handleWXPrepay = function (request, callback) {
    var params = request.query;
    logger.info("handleAppleWeiXinPrePay, ip: %s, body: %j, query: %j", request.ip, request.body, request.query);

    if(!params || !params.body || !params.total_fee || !params.trade_type || !params.attach || !params.appid){
        logger.error("invalid weixinPrePay params: %j", params);
        callback("invalid params");
        return;
    }

    var wxPayConfig = rechargeConfig.wxPayParams[params.appid];
    if(!wxPayConfig){
        logger.error("invalid weixinPrePay appid: %s", params.appid);
        callback("invalid params");
        return;
    }

    //params["appid"] = wxPayConfig.appId;
    params["mch_id"] = wxPayConfig.mch_id;
    params["nonce_str"] = Random.randRange(10101010, 98989898).toString();
    params["out_trade_no"] = TimeUtils.timeTwoFormatByNum(Date.now()) + Random.randRange(101010, 989898).toString();
    params["spbill_create_ip"] = request.ip;
    params["notify_url"] = "http://" + rechargeConfig.rechargeUrl + ":" + rechargeConfig.rechargePort + "/recharge/wxpayNotify";
    params["sign"] = RechargeService.sign(params, wxPayConfig.appKey);

    var builder = new xml2js.Builder({rootName: 'xml', cdata: true});
    var xml = builder.buildObject(params);
    logger.info("WeiXinPrePay request xml: %s", xml);

    var option = {
        url: "https://api.mch.weixin.qq.com/pay/unifiedorder",
        method: 'POST',
        body: xml
    };

    httpRequire(option, function (err, response, body) {
        xml2js.parseString(body, function (error, parseData) {
            if(!!error){
                logger.error("parseString resData failed! body: %s, error: %s", body, error);
                callback("request failed");
                return;
            }

            logger.info("WXPrepay return data: %j", parseData);

            var resJson = parseData.xml;
            if(resJson["return_code"][0] !== "SUCCESS"){
                callback("return_code failed");
                return;
            }

            if(resJson["result_code"][0] !== "SUCCESS"){
                callback("result_code failed");
                return;
            }

            var resParams = {
                appid: wxPayConfig.appId,
                partnerid: wxPayConfig.mch_id,
                prepayid: resJson["prepay_id"][0],
                noncestr: resJson["nonce_str"][0],
                timestamp: Math.round(Date.now() / 1000).toString(),
                package: "Sign=WXPay"
            };

            resParams["sign"] = RechargeService.sign(resParams, wxPayConfig.appKey);
            resParams["return_code"] = "SUCCESS";

            callback(resParams);
        });
    });
};

// 微信发货回调处理
RechargeService.handleWXPayCallback = function (postData, callback) {
    logger.info("handleWXPay Callback, postData: %s", postData);
    var makeReturnXml = function(error){
        var builder = new xml2js.Builder({rootName: 'xml', cdata: true, headless: true});
        return builder.buildObject({return_code: !!error ? "FAIL" : "SUCCESS"});
    };

    xml2js.parseString(postData, function (error, data) {
        if(!!error){
            logger.error("parseString xml failed! error: %s, postData: %s", error, postData);
            callback(makeReturnXml("failed"));
            return;
        }

        var resJson = data.xml;
        var params = {};

        for(var key in resJson){
            params[key] = resJson[key][0];
        }

        RechargeService.dealWeiXinOrder(params, function(result){
            logger.info("dealWeiXinOrder callback: %s", result);
            var xml = makeReturnXml(null);
            //logger.info("dealWeiXinOrder, return: %s", xml);
            callback(xml);
        });
    });
};

/*
 var resParams = {
 "appid":["wx214a5cdea34a63dd"],
 "attach":["apple*100217*1"],
 "bank_type":["CFT"],
 "cash_fee":["1"],
 "fee_type":["CNY"],
 "is_subscribe":["N"],
 "mch_id":["1489228742"],
 "nonce_str":["97633494"],
 "openid":["oQ5ynuEB5MhzNOm3CIZjwtfnoU2k"],
 "out_trade_no":["20160307184340491183"],
 "result_code":["SUCCESS"],
 "return_code":["SUCCESS"],
 "sign":["892F27F03753FEC76ECA53B7C157A324"],
 "time_end":["20160307184423"],
 "total_fee":["1"],
 "trade_type":["APP"],
 "transaction_id":["1007760116201603073799826134"]
 };
 */
RechargeService.dealWeiXinOrder = function (params, callback) {
    logger.info("dealWeiXinOrder, params: %j", params);

    if (!params.attach) {
        logger.error("attach is null!");
        callback("fail");
        return;
    }

    var attach = params.attach.split('*'); //channel*uid*itemIndex
    if (attach.length !== 3) {
        logger.error("invalid attach: %j", attach);
        callback("fail");
        return;
    }

    var channel = attach[0];
    var uid = parseInt(attach[1]);
    var itemIndex = parseInt(attach[2]);

    if (!channel || !uid || typeof(itemIndex) == "undefined") {
        logger.error("invalid attach: %j", attach);
        callback("fail");
        return;
    }

    var return_code = params.return_code;
    var result_code = params.result_code;

    if (return_code !== 'SUCCESS' || result_code !== 'SUCCESS') {
        logger.error("return_code or result_code is not SUCCESS!");
        callback("fail");
        return;
    }

    var orderId = params.transaction_id;
    // var totalFee = Math.round(parseInt(params.total_fee) / 100);
    var totalFee = params.total_fee;

    var wxPayConfig = rechargeConfig.wxPayParams[params.appid];
    if(!wxPayConfig){
        logger.error("weixinPay invalid appid: %s", params.appid);
        callback("fail");
        return;
    }

    var digest = RechargeService.sign(params, wxPayConfig.appKey);

    if (digest !== params.sign) {
        logger.error("sign is not valid. digest: %s, sign: %s", digest, params.sign);
        callback("fail");
        return;
    }

    // 给gameserver发送HTTP充值请求
    var rechargeParams = {};
    rechargeParams.channel = channel;
    rechargeParams.uid = uid;
    rechargeParams.itemIndex = itemIndex;
    rechargeParams.orderId = orderId;
    rechargeParams.totalFee = totalFee;
    rechargeParams.rechargeType = 'wechat';
    RechargeService.sendHttpToGameServer(rechargeParams, callback);
};




RechargeService.handleShengfuRecharge = function (postData, callback) {
    logger.info(`请求收单, ---------------------请求订单-------------------------${JSON.stringify(postData)}`);
    let params = JSON.parse(postData);

    if(!params || !params.account || !params.password || !params.uid) {
        logger.error(`invalid handleShengfuRecharge params: ${JSON.stringify(params)}`);
        callback({resultCode : 404, msg : "invalid params"});
        return;
    }

    let account = "8013360100162175";
    let password = "16561263";

    let nowMs = Date.now();

    //head
    let serviceCode 	= "B2CPayment";								//服务号
    let version 		= "V4.1.1.1.1";								//版本号
    let traceNo 		= "sft" + nowMs; 			                //跟踪号
    let charset 		= "UTF-8";									//字符集
    let senderId		= "592862";                                 //发送方标识(商户号)
    let senderTime	    = TimeUtils.timeTwoFormatByNum(nowMs);
    //body
    let orderNo     	= traceNo;									//订单号
    let orderAmount 	= "1";
    let orderTime 	    = senderTime;
    let expireTime      = TimeUtils.timeTwoFormatByNum(nowMs + 60 * 60 * 60 * 24);
    let currency 	    = "CNY";									//币种
    let language	 	= "zh-CN";									//语言
    let pageUrl         = "http://www.123.com";						//前台地址
    let notifyUrl       = "http://" + rechargeConfig.rechargeUrl + ":" + rechargeConfig.rechargePort + "/recharge/sftRecharge";//后台地址
    let productName 	= "钻石";									//商品名称
    let productNum 	    = "1";										//商品数量
    let unitPrice 	    = "1";								        //商品单价
    let productDesc 	= "钻石";									//商品描述
    let ext1			= params.uid;								//额外的
    let signType        = "MD5";
    let merchantkey     = "zhu2bo0zha1jin6hua";

    let queryString = serviceCode + version + charset + traceNo + senderId + senderTime + orderNo + orderAmount
                    + orderTime + expireTime + currency + language + pageUrl + notifyUrl + productName
                    + productNum + unitPrice + productDesc + ext1 + signType + merchantkey;
    let sign = md5(queryString).toUpperCase();

    let xml = "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"
        +"<soap:Body>"
        +"	<receiveB2COrder>"
        +"		<arg0>"
        +"			<header>"
        +"				<sender>"
        +"					<senderId>" + senderId 		+ "</senderId>"
        +"				</sender>"
        +"				<service>"
        +"					<serviceCode>" 	+ serviceCode 	+ "</serviceCode>"
        +"					<version>" 		+ version 		+ "</version>"
        +"				</service>"
        +"				<charset>" 	+ charset 		+ "</charset>"
        +"				<sendTime>" + senderTime    + "</sendTime>"
        +"				<traceNo>" 	+ traceNo 		+ "</traceNo>"
        +"			</header>"
        +"			<orderNo>" 		+ orderNo 		+ "</orderNo>"
        +"			<orderAmount>" 	+ orderAmount 	+ "</orderAmount>"
        +"			<orderTime>" 	+ orderTime 	+ "</orderTime>"
        +"			<expireTime>" 	+ expireTime 	+ "</expireTime>"
        +"			<currency>" 	+ currency 		+ "</currency>"
        +"			<language>" 	+ language 		+ "</language>"
        +"			<pageUrl>"		+ pageUrl		+ "</pageUrl>"
        +"			<notifyUrl>" 	+ notifyUrl 	+ "</notifyUrl>"
        +"			<productName>"	+ productName	+ "</productName>"
        +"			<productNum>"	+ productNum	+ "</productNum>"
        +"			<unitPrice>"	+ unitPrice		+ "</unitPrice>"
        +"			<productDesc>"	+ productDesc	+ "</productDesc>"
        +"			<extension>"
        +"				<ext1>" 	+ ext1			+ "</ext1>"
        +"			</extension>"
        +"			<signature>"
        +"				<signMsg>" 	+ sign 			+ "</signMsg>"
        +"				<signType>" + signType		+"</signType>"
        +"			</signature>"
        +"		</arg0>"
        +"	</receiveB2COrder>"
        +"</soap:Body>";
    logger.info("handleShengfuRecharge request xml: %s", xml);

    let option = {
        url: "http://cardpay.shengpay.com/api-acquire-channel/services/receiveOrderService",
        method: 'POST',
        body: xml
    };

    httpRequire(option, function (err, response, body) {
        if (!!err) {
            logger.error("httpRequire receiveOrderService failed! body: %s, err: %s", body, err);
            callback({resultCode : 404, msg : "request receiveOrderService failed"});
            return;
        }
        if (response.statusCode === 200) {
            logger.info("支付调用成功！");
            RechargeService.shengfuPay(body, account, password, function (result) {
                callback(result);
            });
        } else {
            logger.info("调用失败！错误码：" + response.statusCode);
            callback({resultCode : 404, msg : "request failed"});
        }
    });
};

RechargeService.shengfuPay = function (responseData, account, password, callback) {
    xml2js.parseString(responseData, function (error, parseData) {
        if(!!error){
            logger.error("shengfuPay parseString resData failed! body: %s, error: %s", responseData, error);
            callback({resultCode : 404, msg : "request failed"});
            return;
        }
        logger.info("ShengfuRecharge return data: %j", parseData);

        let response = parseData["soap:Envelope"]["soap:Body"][0]["ns1:receiveB2COrderResponse"][0]["return"][0];
        let header = response["header"][0];
        if(response["transStatus"][0] !== "00" || !!response.errorCode) {
            logger.info(`shengfuPay transStatus: ${response.transStatus}, errorCode: ${response.errorCode}`);
            callback({resultCode : 404, msg : "transStatus failed"});
            return;
        }
        if (!response["customerNo"]) {
            callback({resultCode : 404, msg : "customerNo null"});
            return;
        }

        let orderNo 		= response["orderNo"];
        let returnInfo 	    = response["returnInfo"];
        //head
        let serviceCode 	= header["service"][0]["serviceCode"][0];		//服务代码
        let version 		= header["service"][0]["version"][0];			//版本号
        let charset 		= header["charset"][0];		                    //字符集
        let traceNo 		= header["traceNo"][0];		                    //请求序列号(d订单号)
        let senderId 	    = header["sender"][0]["senderId"][0];	        //发送方标识
        let sendTime 	    = TimeUtils.timeTwoFormatByNum(Date.now());//发送请求时间
        //B2COrder
        let transNo 		= response["transNo"][0];	  	                //盛付通交易号
        let orderAmount 	= response["orderAmount"][0];	  	            //订单金额
        let orderType 	    = "OT001";						                //请求类型
        //B2CPayment
        let payChannel 	    = "42";						                    //渠道编号见附录【支付渠道】内容
        let payerId		    = "";
        let cardInfo 	    = account + "_" + password;
        let tokenId 		= response["tokenId"][0];	 		            //支付令牌
        let sessionId 	    = response["sessionId"][0];			            //会话标识

        let ptId	 		= "4315";
        let ptIdType		= "1001";
        let accountId	    = "2367578001@qq.com";
        let ext1			= response["extension"][0]["ext1"][0];	       		//额外的
        let signType        = "MD5";
        let merchantkey     = "zhu2bo0zha1jin6hua";

        let queryString = serviceCode + version + charset + traceNo + senderId + sendTime + transNo + orderAmount
            + orderType + ptIdType + accountId + payChannel + "PAYER_IP" + "127.0.0.1" + "CARD_INFO"
            + cardInfo + tokenId + sessionId + ext1 + signType + merchantkey;
        let sign = md5(queryString).toUpperCase();

        let xml = "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"> "
            +"	<soap:Body>"
            +"		<processB2CPay>"
            +"			<arg0>"
            +"				<header>"
            +"					<traceNo>" 		+ traceNo 	+ "</traceNo>"
            +"					<charset>UTF-8</charset>"
            +"					<sendTime>" 	+ sendTime  + "</sendTime>"
            +"					<sender>"
            +"						<senderId>" + senderId 	+ "</senderId>"
            +"					</sender>"
            +"					<service>"
            +"						<serviceCode>" + serviceCode + "</serviceCode>"
            +"						<version>"     + version 	 + "</version>"
            +"					</service>"
            +"				</header>"
            +"				<order>"
            +"					<transNo>" 		+ transNo 		+ "</transNo>"
            +"					<orderAmoumt>" 	+ orderAmount 	+ "</orderAmoumt>"
            +"					<orderType>" 	+ orderType	 	+ "</orderType>"
            +"				</order>"
            +"  			<payer>"
            +"  				<ptIdType>"		+ ptIdType 		+ "</ptIdType>"
            +"  			</payer>"
            +"  			<payee>"
            +"  				<accountId>"	+ accountId 	+ "</accountId>"
            +"  			</payee>"
            +"				<payment>"
            +"					<payChannel>" 	+ payChannel 	+ "</payChannel>"
            +"					<paymentItems>"
            +"						<key>PAYER_IP</key>"
            +"						<value>127.0.0.1</value>"
            +" 					</paymentItems>"
            +"					<paymentItems>"
            +"						<key>CARD_INFO</key>"
            +"						<value>"	+ cardInfo 		+ "</value>"
            +" 					</paymentItems>"
            +"				</payment>"
            +"				<extension>"
            +"					<ext1>" 	+ ext1			+ "</ext1>"
            +"				</extension>"
            +"				<signature>"
            +"					<signType>"		+ signType		+ "</signType>"
            +"					<signMsg>" 		+ sign 		+ "</signMsg>"
            +"				</signature>"
            +"				<tokenId>"	 + tokenId		+ "</tokenId>"
            +"				<sessionId>" + sessionId	+ "</sessionId>"
            +"			</arg0>"
            +"		</processB2CPay>"
            +"</soap:Body>";
        logger.info("shengfuPay request xml: %s", xml);

        let option = {
            url: "http://cardpay.shengpay.com/api-acquire-channel/services/paymentService",
            method: 'POST',
            body: xml
        };
        httpRequire(option, function (err, response, body) {
            if (!!err) {
                logger.error("httpRequire paymentService failed! body: %s, err: %s", body, err);
                callback({resultCode : 404, msg : "request paymentService failed"});
                return;
            }
            if (response.statusCode === 200) {
                logger.info(`支付调用成功！`);
                xml2js.parseString(body, function (error, parseData) {
                    logger.info("ShengfuRecharge return data: %j", parseData);
                    let responseData = parseData["soap:Envelope"]["soap:Body"][0]["ns1:processB2CPayResponse"][0]["return"][0];
                    if(responseData["transStatus"][0] === "01"){
                        callback({resultCode: 0, msg: "ok"});
                    } else if (responseData["transStatus"][0] === "00") {
                        callback({resultCode: 404, msg: "error"});
                    } else {
                        callback({resultCode: 404, msg: "error"});
                    }
                });
                // callback(resParams);

            } else {
                logger.info("调用失败！错误码：" + response.statusCode);
            }
        });
    });
};


RechargeService.sendHttpToGameServer = function (params, callback) {
    var option = {
        url: rechargeConfig.gameServerRechargeUrl,
        method: 'POST',
        json: params
    };

    logger.info("send Recharge To GameServer... url: %s", option.url);
    logger.info("send Recharge To GameServer..., prams: %s", JSON.stringify(params));
    httpRequire(option, function (err, resp, body) {
        // TODO:和游戏服通讯回包处理
        // logger.error("sendHttpToGameServer resp: %j", JSON.stringify(resp));
        logger.info("sendHttpToGameServer resp.statusCode: %j", resp ? resp.statusCode : null);
        if(!!err){
            logger.error("url: " + option.url + ", err: " + err);
            callback('failed');
            return;
        }

        callback(null);
        logger.info("sendHttpToGameServer callback ok");
    });

};

RechargeService.sign = function (param, appKey) {
    var filterKeys = ['pfx', 'partner_key', 'sign', 'key'];

    var queryString = Object.keys(param).filter(function (key) {
        //return param[key] !== undefined && param[key] !== '' && ['pfx', 'partner_key', 'sign', 'key'].indexOf(key) < 0;
        return filterKeys.indexOf(key) < 0;
    }).sort().map(function (key) {
        return key + '=' + param[key];
    }).join("&");

    queryString += "&key=" + appKey;
    return md5(queryString).toUpperCase();
};

module.exports.handleWXPrepay = RechargeService.handleWXPrepay;
module.exports.handleWXPayCallback = RechargeService.handleWXPayCallback;
module.exports.handleWyxPay = RechargeService.handleWyxPay;
module.exports.handleShengfuRecharge = RechargeService.handleShengfuRecharge;